package com.dc.project.sales.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dc.common.annotation.DataScope;
import com.dc.common.constant.CustomSqlConstants;
import com.dc.common.constant.PrefixConstants;
import com.dc.common.constant.TableConstants;
import com.dc.common.constant.WorkflowConstants;
import com.dc.common.core.MasterSlaveDto;
import com.dc.common.exception.ServiceException;
import com.dc.common.utils.*;
import com.dc.common.vo.ResultVo;
import com.dc.project.gen.utils.GenerateCodeUtil;
import com.dc.project.sales.dao.SalOrderDao;
import com.dc.project.sales.dto.SalOrderDto;
import com.dc.project.sales.entity.SalOrder;
import com.dc.project.sales.entity.SalOrderDetail;
import com.dc.project.sales.service.SalOrderDetailService;
import com.dc.project.sales.service.SalOrderService;
import com.dc.project.workflow.service.ActFlowService;
import com.dc.project.workflow.service.WfDocProcessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 销售订单表(SalOrder)表服务实现类
 *
 * @author zhuangcy
 * @since 2021-06-12 16:37:09
 */
@Service("salOrderService")
public class SalOrderServiceImpl extends ServiceImpl<SalOrderDao, SalOrder> implements SalOrderService, WfDocProcessService {
    @Autowired
    private SalOrderDetailService salOrderDetailService;
    @Autowired
    private ActFlowService actFlowService;

    /**
     * 通过主键查询单条数据
     *
     * @param id 主键
     * @return
     */
    @Override
    public ResultVo queryById(Serializable id) {
        return ResultVo.success().data(this.getById(id));
    }

    /**
     * 分页查询销售订单表
     *
     * @param dto
     * @return
     */
    @DataScope
    @Override
    public ResultVo queryByPage(SalOrderDto dto) {
        QueryWrapper<SalOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .like(StringUtil.isNotEmpty(dto.getClienteleName()), SalOrder::getClienteleName, dto.getClienteleName())
                .like(StringUtil.isNotEmpty(dto.getDocCode()), SalOrder::getDocCode, dto.getDocCode())
                .like(StringUtil.isNotEmpty(dto.getSalesman()), SalOrder::getSalesman, dto.getSalesman())
                .ge(ObjectUtil.isNotEmpty(dto.getStartTime()), SalOrder::getDocDate, dto.getStartTime())
                .le(ObjectUtil.isNotEmpty(dto.getEndTime()), SalOrder::getDocDate, dto.getEndTime())
                .apply(ObjectUtil.getDataScopeSql(dto))
                .orderByDesc(SalOrder::getOrderId);
        IPage<SalOrder> page = this.page(PageUtil.convert2PageParam(dto), queryWrapper);
        return ResultVo.success().data(PageUtil.convert2PageResult(page));
    }

    /**
     * 新增销售订单表
     *
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultVo add(MasterSlaveDto<SalOrder, SalOrderDetail> dto) {
        SalOrder salOrder = dto.getMaster();
        salOrder.setStatus(WorkflowConstants.DOC_SAVE_STATE);
        salOrder.setDocCode(GenerateCodeUtil.getDefaultDateCode(PrefixConstants.SALES_ORDER_PREFIX, TableConstants.SALES_ORDER));
        if (this.save(salOrder)) {
            List<SalOrderDetail> salOrderDetails = dto.getSlaves().stream().map(item -> {
                item.setOrderId(salOrder.getOrderId());
                return item;
            }).collect(Collectors.toList());
            if (salOrderDetailService.saveBatch(salOrderDetails, salOrderDetails.size())) {
                // 在新增这里创建审批流程
                actFlowService.createDocProcess(salOrder.getDocCode(), SalOrder.DOC_TYPE_NAME);
                return ResultVo.success();
            }
        }
        throw new ServiceException();
    }

    /**
     * 编辑销售订单表
     *
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultVo edit(MasterSlaveDto<SalOrder, SalOrderDetail> dto) {
        SalOrder salOrder = dto.getMaster();
        SalOrder order = this.getById(salOrder.getOrderId());
        if (null == order) {
            throw new ServiceException();
        } else if (WorkflowConstants.DOC_SAVE_STATE.equals(order.getStatus()) || WorkflowConstants.DOC_REVOKE_STATE.equals(order.getStatus())) {
            salOrder.setStatus(WorkflowConstants.DOC_SAVE_STATE);
            if (this.updateById(salOrder)) {
                List<Integer> ids = dto.getIds();
                if (null != ids && !ids.isEmpty()) {
                    salOrderDetailService.removeByIds(ids);
                }
                List<SalOrderDetail> salOrderDetails = dto.getSlaves().stream().map(item -> {
                    if (null == item.getOrderId()) {
                        item.setOrderId(salOrder.getOrderId());
                    }
                    return item;
                }).collect(Collectors.toList());
                if (salOrderDetailService.saveOrUpdateBatch(salOrderDetails, salOrderDetails.size())) {
                    return ResultVo.success();
                }
            }
        }

        return ResultVo.success();
    }

    /**
     * 根据主键删除销售订单表
     *
     * @param id 主键
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultVo delete(Serializable id) {
        SalOrder order = this.getById(id);
        if (null == order) {
            throw new ServiceException("该单据不存在");
        }
        if (WorkflowConstants.DOC_SAVE_STATE.equals(order.getStatus())
                || WorkflowConstants.DOC_REVOKE_STATE.equals(order.getStatus())
                || WorkflowConstants.DOC_APPROVED_NOT_STATE.equals(order.getStatus())) {
            if (this.removeById(id)) {
                LambdaQueryWrapper<SalOrderDetail> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(SalOrderDetail::getOrderId, id);
                salOrderDetailService.remove(queryWrapper);
                // 删除流程信息
                actFlowService.deleteDocProcess(order.getDocCode(), SalOrder.DOC_TYPE_NAME);
                return ResultVo.success();
            }
            throw new ServiceException("删除失败");
        }
        return ResultVo.failed().msg("删除失败，该单据已受理");
    }

    /**
     * 销售订单批量提交
     *
     * @param ids
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultVo submit(List<Integer> ids) {
        LambdaQueryWrapper<SalOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(SalOrder::getOrderId, ids)
                // 已保存、已撤回的单据
                .and(wrapper -> wrapper.eq(SalOrder::getStatus, WorkflowConstants.DOC_SAVE_STATE)
                        .or().eq(SalOrder::getStatus, WorkflowConstants.DOC_REVOKE_STATE));
        List<SalOrder> list = this.list(queryWrapper);
        if (list.isEmpty()) {
            return ResultVo.failed().msg("提交失败，未找到可提交单据，检查是否已撤回");
        }
        List<SalOrder> submitList = list.stream().map(item -> {
            item.setStatus(WorkflowConstants.DOC_SUBMIT_STATE);
            return item;
        }).collect(Collectors.toList());
        if (this.updateBatchById(submitList, submitList.size())) {
            for (SalOrder order : submitList) {
                // 提交单据流程
//                Map<String, Object> map = BeanUtil.beanToMap(order);
                Map<String, Object> map = new HashMap<>();
                map.put("totalAmount", order.getTotalAmount());
                actFlowService.submitDocTask(order.getDocCode(), SalOrder.DOC_TYPE_NAME, map);
            }
            return ResultVo.success().msg(StringUtil.format("共{}条单据已成功提交", ids.size()));
        }

        throw new ServiceException();
    }

    /**
     * 销售订单批量撤回
     *
     * @param ids
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultVo revoke(List<Integer> ids) {
        LambdaQueryWrapper<SalOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(SalOrder::getOrderId, SalOrder::getStatus, SalOrder::getDocCode)
                .in(SalOrder::getOrderId, ids)
                // 已提交、不通过的才能撤回
                .and(wrapper -> wrapper.eq(SalOrder::getStatus, WorkflowConstants.DOC_SUBMIT_STATE)
                        .or().eq(SalOrder::getStatus, WorkflowConstants.DOC_APPROVED_NOT_STATE));
        List<SalOrder> list = this.list(queryWrapper);
        if (list.isEmpty()) {
            return ResultVo.failed().msg("撤回失败，未找到可撤回单据，请检查是否已提交");
        }
        List<SalOrder> submitList = list.stream().map(item -> {
            item.setStatus(WorkflowConstants.DOC_REVOKE_STATE);
            return item;
        }).collect(Collectors.toList());
        if (this.updateBatchById(submitList, submitList.size())) {
            for (SalOrder order : submitList) {
                // 回退单据流程
                HashMap<String, Object> map = new HashMap<>();
                BeanUtil.copyBeanProp(map, order);
                actFlowService.revokeDocTask(order.getDocCode(), SalOrder.DOC_TYPE_NAME, map);
            }
            return ResultVo.success().msg(StringUtil.format("共{}条单据已成功撤回", ids.size()));
        }

        throw new ServiceException();
    }

    /**
     * 通过单据号查询单条数据
     *
     * @param docCode
     * @return
     */
    @Override
    public ResultVo getOneByDocCOde(String docCode) {
        LambdaQueryWrapper<SalOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SalOrder::getDocCode, docCode)
                .last(CustomSqlConstants.LIMIT_1);
        SalOrder one = this.getOne(queryWrapper);
        return ResultVo.success().data(one);
    }

    /**
     * 修改单据状态
     *
     * @param businessKey 单据标识
     * @param status      改后状态
     */
    @Override
    public void updateDocStatus(String businessKey, String status) {
        UpdateWrapper<SalOrder> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().set(SalOrder::getStatus, status)
                .eq(SalOrder::getDocCode, businessKey);
        this.update(updateWrapper);
    }

    /**
     * 获取单据状态
     *
     * @param businessKey 单据标识
     */
    @Override
    public String getDocStatus(String businessKey) {
        LambdaQueryWrapper<SalOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SalOrder::getDocCode, businessKey)
                .last(CustomSqlConstants.LIMIT_1);
        SalOrder one = this.getOne(queryWrapper);
        if (null == one) {
            throw new ServiceException("未找到单据信息");
        }
        return one.getStatus();
    }
}